package com.shermanzhou.aop.log;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * @author zhouchaoqun
 * @date 2018/9/12 上午10:18
 */
@Component
@Aspect
public class ActionLogAspect {

    @Autowired
    private ActionLogHandler actionLogHandler;

    @Pointcut("@annotation(com.shermanzhou.aop.log.ActionLog)")
    public void pointCut(){}

    @Around("pointCut()")
    public void around(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs();
        ActionLog annotation = getActionLogAnnotation(pjp);
        String handleMethodName = annotation.handleMethodName();
        String paramIndex = annotation.paramIndex();
        Object[] params = new Object[args.length];
        Class<?>[] paramsType = new Class<?>[params.length];
        if (!StringUtils.isEmpty(paramIndex)) {
            System.out.println(paramIndex);
            String[] idxs = paramIndex.split(",");
            for (int i = 0; i < idxs.length; i++) {
                params[i] = args[Integer.parseInt(idxs[i])];
                paramsType[i] = params[i].getClass();
            }
        }


        Method method = actionLogHandler.getClass().getMethod(handleMethodName, paramsType);
        Object invoke = method.invoke(actionLogHandler, params);
        pjp.proceed();
    }

    private ActionLog getActionLogAnnotation(ProceedingJoinPoint pjp) throws NoSuchMethodException {
        Signature sig = pjp.getSignature();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Object target = pjp.getTarget();
        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        return currentMethod.getAnnotation(ActionLog.class);
    }
}
